home *** CD-ROM | disk | FTP | other *** search
- /*
- *
- * blt2cx03.c - 17-Oct-1995 Cornel Huth
- * This module is called by blt2demo.c
- * INSERT_XB
- *
- */
-
- #include "platform.h"
-
- #ifdef ON_OS2
- #include <os2.h>
- #endif
- #ifdef ON_W95
- #define WIN32_LEAN_AND_MEAN
- #include <windows.h>
- #endif
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <time.h>
- #include <string.h>
-
- #ifdef ON_OS2
- #include "bullet2.h"
- #endif
- #ifdef ON_W95
- #include "bullet95.h"
- #endif
- #ifdef ON_DOSX
- #include "bulletx.h"
- #endif
-
- void cx03BuildFieldList(FIELDDESCTYPE fieldList[]);
-
- extern CHAR *collateTable;
-
-
- int cx03() {
-
- #pragma pack(1)
-
- ACCESSPACK AP;
- DOSFILEPACK DFP;
- CREATEDATAPACK CDP;
- CREATEINDEXPACK CIP;
- HANDLEPACK HP;
- OPENPACK OP;
-
- struct EmpRecType {
- CHAR tag; // record tag, init to SPACE, * means deleted
- CHAR empID[9]; // SSN (not 0T string)
- CHAR empLN[16]; // last name
- CHAR empFN[16]; // first name
- CHAR empHire[8]; // "YYYYMMDD" (not 0T string)
- CHAR empDept[6]; // department assigned
- }; // 56 bytes
- struct EmpRecType EmpRec;
-
- #pragma pack()
-
- time_t startTime, endTime;
- int display = 0; // display results or not flag
- int sameSequence = 1; // use same random seed each time
- int rndSeqVar = 0; // random "key" generated (9 digits worth)
-
- LONG rez; // return value from Bullet
-
- CHAR nameIX3[] = "$CX03.IX3"; // name of index file created
- ULONG indexID=0; // handle of index file
- CHAR keyExpression[128]; // key expression string buffer (159 max)
- CHAR keyBuffer[68]; // buffer used to store/receive key values
-
- CHAR nameData[] = "$CX03.DBF"; // name of data file created
- ULONG dataID=0; // handle of data file
- FIELDDESCTYPE fieldList[5]; // 5 fields used in data record
-
- LONG recs2add; // records to add en-masse
- LONG i; // counter
- CHAR tmpStr[64]; // misc stuff, non-Bullet related
-
- printf("INSERT_XB, an all-or-nothing transaction insert into up to\n");
- printf("256 files (total of 512 data and index files) from a single call.\n\n");
-
- // note that this particular example uses only a single index/data file DB
-
- memset(fieldList,0,sizeof(fieldList)); // init unused bytes to 0 (required)
- cx03BuildFieldList(fieldList);
-
- // Delete previous files from any previous run (disregard any error return)
-
- DFP.func = DELETE_FILE_DOS;
- DFP.filenamePtr = nameData;
- rez = BULLET(&DFP);
- DFP.filenamePtr = nameIX3;
- rez = BULLET(&DFP);
-
-
- // Create the data file, a standard DBF (ID=3) as defined in fieldList above.
-
- CDP.func = CREATE_DATA_XB;
- CDP.filenamePtr = nameData;
- CDP.noFields = 5;
- CDP.fieldListPtr = fieldList;
- CDP.fileID = 0x03;
- rez = BULLET(&CDP);
- if (rez) {
- printf("Failed data file create. Err: %li\n",rez);
- goto Abend;
- }
-
-
- // Open the data file (required before creating an index file for it)
-
- OP.func = OPEN_DATA_XB;
- OP.filenamePtr = nameData;
- OP.asMode = READWRITE | DENYNONE;
- rez = BULLET(&OP);
- if (rez) {
- printf("Failed data file open. Err: %li\n",rez);
- goto Abend;
- }
- dataID = OP.handle;
-
-
- // Create an index file for the data file opened above.
- // This example uses a single, 9-byte key -- the SSN.
-
- strcpy(keyExpression,"SSN");
-
- CIP.func = CREATE_INDEX_XB;
- CIP.filenamePtr = nameIX3;
- CIP.keyExpPtr = keyExpression;
- CIP.xbLink = dataID; // the handle of the data file
- CIP.sortFunction = ASCII_SORT; // sort by ASCII order (fine for text numbers)
- CIP.codePage = CODEPAGE; // code page
- CIP.countryCode = CTRYCODE; // country code
- CIP.collatePtr = NULL; // -- ASCII_SORT, no collate table is used
- CIP.nodeSize = 512; // 512-byte node size (or 1024, 2048 bytes)
- rez = BULLET(&CIP);
- if (rez) {
- printf("Failed index file create. Err: %li\n",rez);
- goto Abend;
- }
-
-
- // Open the index file (what we just created above).
-
- OP.func = OPEN_INDEX_XB;
- OP.filenamePtr = nameIX3;
- OP.asMode = READWRITE | DENYNONE;
- OP.xbLink = dataID;
- rez = BULLET(&OP);
- if (rez) {
- printf("Failed index file open. Err: %li\n",rez);
- goto Abend;
- }
- indexID = OP.handle;
-
-
- // Have created and opened both data file and index files.
- // The next section inserts record and key with the single call, and removes
- // them (or any changes) if and error occured along the way.
-
- printf("Display all data accessed (slower results)? (y/N) ");
- gets(tmpStr);
- if (*tmpStr=='y') display = 1;
-
- printf(" Repeat same random key sequence? (Y/n) ");
- gets(tmpStr);
- if (*tmpStr=='n') sameSequence = 0;
-
- printf(" How many records do you want for this test run? ");
- gets(tmpStr);
- recs2add = atol(tmpStr);
- if (recs2add < 1) recs2add = 1; // would you rather end the test?
- if (recs2add > 9999999) recs2add = 1; // why wait around for 10M?
-
- // Add the data records, which are created here, on-the-fly, varying enough
- // to make unique records. The key is inserted for each record added.
-
- // setup invariant parts of data record out of loop
-
- EmpRec.tag = ' '; // set to not-deleted
- strncpy(EmpRec.empID,"000000000",9); // the key.field
- strcpy(EmpRec.empLN,"YourLastName"); // everyone has the same last name
- strcpy(EmpRec.empFN,"YourFirstName"); // everyone has this first name!
- strncpy(EmpRec.empHire,"19950618",8); // YYYYMMDD DBF form, no \0 on date
- strcpy(EmpRec.empDept,"MIS"); // everyone works for MIS!
-
- // The record construction creates a pretty random SSN number (.empID)
- // and that is used as the key -- the key is kept unique (i.e., duplicate
- // .empID values are not allowed). In case of a duplicate (likely given
- // the SSN generation technque), the changes made to the database are
- // backed out by BULLET. Another insert is made to cover the count requested.
-
- if (sameSequence)
- srand(1);
- else
- srand((unsigned)time(0));
-
- printf("Inserting %ld recs/keys.. ",recs2add);
- time(&startTime);
-
- AP.func = INSERT_XB;
- AP.handle = indexID;
- AP.keyPtr = keyBuffer;
- AP.recPtr = &EmpRec;
- AP.nextPtr = NULL;
-
- for (i = 1; i <= recs2add; i++) {
-
- rndSeqVar = (rand() >> 1) * (rand() >> 2); // 16383*8191=134193153 max
- sprintf(tmpStr,"%9.9i",rndSeqVar);
- strncpy(EmpRec.empID,tmpStr,9); // update SSN
-
- // on an INSERT_XB, .recNo has special meaning on input and
- // must be 0 (unless one of two special cases -- see docs)
-
- AP.recNo = 0;
-
- rez = BULLET(&AP); // AP. already setup
- if (rez) {
-
- // Since only a single AP pack, on an error rez will be 1 (or -1)
- // this because INSERT_XB is a transaction routine and its return
- // code (rez) is the number of the pack that failed (1 being the first)
- // -- additionally, the number is made negative to identify the error
- // as originating from the data record portion of the insert --
-
- // negative rc means failed during data record add
-
- if (rez < 0) {
- rez = AP.stat;
- printf("Failed during data portion, sequence %ld. Err: %lu\n",i,rez);
- goto Abend;
- }
-
- // otherwise during index key insert
-
- else {
- rez = AP.stat;
-
- // The random key generated exists, and since field is SSN which is
- // usually unique enough, let's just ignore this (the data record
- // has automatically be removed already) and do another insert to
- // cover the recs2add amount entered by the user (user=you here).
-
- // NOTE: EXB_KEY_EXISTS can be handled by Bullet if during the index
- // create the DUPS_ALLOWED flag were specified, but that would make
- // the key two bytes longer, and since SSN, for practical purposed
- // should be unique (it's said it's not...), just assume this dup
- // never occured.
-
- if (rez == EXB_KEY_EXISTS) {
- rez = 0;
- i--;
- }
- else {
- printf("Failed during index portion, sequence %ld. Err: %lu\n",i,rez);
- goto Abend;
- }
- }
- }
- }
- time(&endTime);
- printf("took %lu secs.\n",(endTime - startTime));
-
-
- memset(keyBuffer,0,sizeof(keyBuffer)); // gives the \0 to the returned key
-
- printf(" Accessing %ld keys... ",recs2add);
- if (display) printf("\n");
- time(&startTime);
- AP.func = FIRST_KEY_XB;
- AP.handle = indexID;
- AP.keyPtr = keyBuffer;
- rez = BULLET(&AP);
- i=0;
- while (rez==0) {
- i++;
- if (display) printf("%s %9.9lu\r", keyBuffer, AP.recNo);
- AP.func = NEXT_KEY_XB;
- rez = BULLET(&AP);
- };
- if (display) printf("\n...");
-
- // expected rez is EXB_END_OF_FILE
-
- if (rez!=EXB_END_OF_FILE) {
- printf("Failed KEY access. Err: %li\n",rez);
- goto Abend;
- }
- time(&endTime);
- printf("took %lu secs. for %ld keys\n",(endTime - startTime),i);
-
-
- printf(" Accessing %ld keys+recs...",recs2add);
- if (display) printf("\n");
- time(&startTime);
- AP.func = GET_FIRST_XB;
- AP.handle = indexID;
- AP.keyPtr = keyBuffer;
- AP.recPtr = &EmpRec;
- rez = BULLET(&AP);
- i=0;
- while (rez==0) {
- i++;
- if (display)
- printf("%s %9.9lu %s\r", keyBuffer, AP.recNo, &EmpRec); // to first \0
- AP.func = GET_NEXT_XB;
- rez = BULLET(&AP);
- };
- if (display) printf("\n...");
-
- // expected rez is EXB_END_OF_FILE
-
- if (rez!=EXB_END_OF_FILE) {
- printf("Failed GET access. Err: %li\n",rez);
- goto Abend;
- }
- time(&endTime);
- printf("took %lu secs. for %ld keys & records\n",(endTime - startTime),i);
-
- // Fatal errors above come straight to here
- Abend:
-
- // Close files (index files first then data (recommended but not required))
-
- if (indexID) {
- HP.func = CLOSE_INDEX_XB;
- HP.handle = indexID;
- rez = BULLET(&HP);
- if (rez)
- printf("Failed index file close. Err: %li\n",rez);
- }
-
- if (dataID) {
- HP.func = CLOSE_DATA_XB;
- HP.handle = dataID;
- rez = BULLET(&HP);
- if (rez)
- printf("Failed data file close. Err: %li\n",rez);
- }
-
- return rez; // program exit
- }
-
- //------------------------------------
- // Init field list items for data file
-
- void cx03BuildFieldList(FIELDDESCTYPE fieldList[]) {
-
- strcpy(fieldList[0].fieldName, "SSN");
- fieldList[0].fieldType = 'C';
- fieldList[0].fieldLen = 9;
- fieldList[0].fieldDC = 0;
-
- strcpy(fieldList[1].fieldName, "LNAME");
- fieldList[1].fieldType = 'C';
- fieldList[1].fieldLen = 16;
- fieldList[1].fieldDC = 0;
-
- strcpy(fieldList[2].fieldName, "FNAME");
- fieldList[2].fieldType = 'C';
- fieldList[2].fieldLen = 16;
- fieldList[2].fieldDC = 0;
-
- strcpy(fieldList[3].fieldName, "HIRED");
- fieldList[3].fieldType = 'D';
- fieldList[3].fieldLen = 8; // date field type must be 8.0
- fieldList[3].fieldDC = 0;
-
- strcpy(fieldList[4].fieldName, "DEPT");
- fieldList[4].fieldType = 'C';
- fieldList[4].fieldLen = 6;
- fieldList[4].fieldDC = 0;
- }
-